// Euler angle implementation

#ifndef ANGLETEM_H
#define ANGLETEM_H

#include "imMaths.h"

template <typename Real>
struct AngleTem {
	union {
		struct {
			Real p, y, r;
		};
		Real Data[3];
	};

	AngleTem<Real>(void) { p=0.0,y=0.0,r=0.0; } // p=0 y=0 r=0
	AngleTem<Real>(Real _p, Real _y, Real _r) { p=_p,y=_y,r=_r; } // p=a y=b r=c
	AngleTem<Real>(Vector3Tem<Real> v){ // Vector3 to Angle
		Real HorizontalLength = sqrt(v.x*v.x + v.z*v.z);
		p = -atan2(v.y, HorizontalLength);
		y = -atan2(-v.x, v.z);
		r = 0.0;
	}

	Vector3Tem<Real> Forward(void) { // Forward vector
		Vector3Tem<Real> f(	sin(r) * sin(p) + cos(r) * sin(y) * cos(p),
							-cos(r) * sin(p) + sin(r) * sin(y) * cos(p),
							cos(y) * cos(p));

		//f.Normalize();
		return f;
	}
	Vector3Tem<Real> Right(void) { // Right vector
		Vector3Tem<Real> f(	cos(r) * cos(y),
							sin(r) * cos(y),
							-sin(y));

		//f.Normalize();
		return f;
	}
	Vector3Tem<Real> Up(void) { // Up vector
		Vector3Tem<Real> f(	-sin(r) * cos(p) + cos(r) * sin(y) * sin(p),
							cos(r) * cos(p) + sin(r) * sin(y) * sin(p),
							cos(y) * sin(p));

		//f.Normalize();
		return f;
	}

	AngleTem<Real> operator+(const AngleTem<Real> &a){
		return Angle(p + a.p, y + a.y, r + a.r);
	}
	AngleTem<Real> operator-(const AngleTem<Real> &a) {
		return Angle(p - a.p, y - a.y, r - a.r);
	}
	AngleTem<Real> operator*(const AngleTem<Real> &a) {
		return Angle(p * a.p, y * a.y, r * a.r);
	}
	AngleTem<Real> operator/(const AngleTem<Real> &a) {
		return Angle(p / a.p, y / a.y, r / a.r);
	}
	AngleTem<Real> operator+=(const AngleTem<Real> &a) {
		p += a.p;
		y += a.y;
		r += a.r;
		return *this;
	}
	AngleTem<Real> operator-=(const AngleTem<Real> &a) {
		p -= a.p;
		y -= a.y;
		r -= a.r;
		return *this;
	}
	AngleTem<Real> operator*=(const AngleTem<Real> &a) {
		p *= a.p;
		y *= a.y;
		r *= a.r;
		return *this;
	}
	AngleTem<Real> operator/=(const AngleTem<Real> &a) {
		p /= a.p;
		y /= a.y;
		r /= a.r;
		return *this;
	}

	AngleTem<Real> operator*(Real) {
		return Angle(p*a, y*a, r*a);
	}
	AngleTem<Real> operator/(Real) {
		return Angle(p/a, y/a, r/a);
	}
	AngleTem<Real> operator*=(Real) {
		p *= a;
		y *= a;
		r *= a;
		return *this;
	}
	AngleTem<Real> operator/=(Real) {
		p /= a;
		y /= a;
		r /= a;
		return *this;
	}
};

typedef AngleTem<float> Angle;
typedef AngleTem<float> Anglef;
typedef AngleTem<double> Angled;

#endif